#coding=utf-8
#LightCam IPSLA监控程序
#init by hfh 20150212

import multiprocessing,subprocess,threading
import socket,os,time,re,traceback,sys
import lc_libs,pymongo
import telnetlib,base64
import pexpect


def func(this):
	devicename=this['devicename']
	deviceip=this['deviceip']
	interval=this['interval']
	threshold=int(this['threshold'])
	devicetype=this['devicetype']
	severity=this['severity']
	schedule=this['schedule']
	holiday=this['holiday']

	USER="monitor"
	PASSWD="IWNmZkV4MjAwN1w="

	Node=devicename
	AlertGroup="IPSLA"
	AlertKey=devicename
	Summary=""
	
	deviceinfo={}
	deviceinfo['MX960']={}
	deviceinfo['MX960']['cmd']="show service rpm probe-results"
	deviceinfo['MX960']['pwd']="password:"
	deviceinfo['CISCO']={}
	deviceinfo['CISCO']['cmd']="show ip sla summary"
	deviceinfo['CISCO']['pwd']="Password:"
	deviceinfo['CISC2']={}
	deviceinfo['CISC2']['cmd']="show ip sla statistics"
	#deviceinfo['CISC2']['cmd']="cat /tmp/ipsla2.log"
	deviceinfo['CISC2']['pwd']="password:"

	#test
	#USER="imonitor"
	#PASSWD="YWRtaW4xMjM=\n"	
	#deviceip="172.31.112.246"
	
	try:
		ssh=pexpect.spawn('ssh %s@%s "%s"' % (USER,deviceip,deviceinfo[devicetype]['cmd']))
		i=ssh.expect([deviceinfo[devicetype]['pwd'],'continue connecting (yes/no)?'],timeout=5)
		ssh.sendline(base64.decodestring(PASSWD))
		strs=ssh.readlines()
		ssh.close()
		res={}
		resultList=[]
		flag=0
		if devicetype == 'MX960':
			for line in strs:
				if "Owner:" in line:
					flag=1
				elif "Target address" in line:
					Target=re.findall(r"\d+.\d+.\d+.\d+",line,re.S)[0]
				elif "Rtt:" in line:
					Rtt=re.findall(r'\d+',line,re.S)[0]
				elif "Loss" in line and flag==1:
					Loss=int(re.findall(r'\d+',line,re.S)[2])
					if Loss == 0:	Loss="OK"
					res['Target']=serverinfo[Target]
					res['Rtt']=int(Rtt)
					res['Loss']=Loss
					resultList.append(res)
					res={}
					flag=0
				else:
					continue
		elif devicetype == 'CISCO':
			for line in strs:
				if "icmp-echo" in line:
					(Target,Rtt,Loss)=re.search("(\d+.\d+.\d+.\d+).*RTT=(\d+)\s+(\w+)\s+",line).groups()
					res['Target']=serverinfo[Target]
					res['Rtt']=int(Rtt)*1000
					res['Loss']=Loss
					resultList.append(res)
					res={}
				else:
					continue
		elif devicetype == 'CISC2':
			for line in strs:
				if "Round Trip Time" in line:
					Target=re.search("(\d{1,})",line).groups()[0]
					Target=index[Target]
				elif "Latest RTT" in line: 
					Rtt=re.search("(\d{1,})",line).groups()[0]
				elif "return code" in line: 
					Loss=re.search(": ([a-zA-Z]+)",line).groups()[0]
					res['Target']=serverinfo[Target]
					res['Rtt']=int(Rtt)*1000
					res['Loss']=Loss
					resultList.append(res)
					res={}
				else:
					continue
		else:
			logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
			logfile.write(logdate+" :\n"+AlertKey+" Unknow Device Type : "+devicetype+"\n")
			logfile.flush()
		
		for result in resultList:
			AlertKey=devicename+"-"+result['Target']+"-RTT"
			if result['Rtt'] < threshold:
				Severity="1"
				Type="2"
				Summary="%s到%s延迟为%susec,小于设定的阈值%susec" % (devicename,result['Target'],result['Rtt'],threshold)
			else:
				Severity=severity
				Type="1"
				Summary="%s到%s延迟为%susec,超过设定的阈值%susec" % (devicename,result['Target'],result['Rtt'],threshold)
			strs=lc_libs.lc_gen_alert(devicename,devicename,AlertGroup,AlertKey,Severity,Type,Summary)
			db.update_eventsdb(events_table,devicename,Node,AlertGroup,AlertKey,Severity,Type,Summary)
			print strs
			
			AlertKey=devicename+"-"+result['Target']+"-Loss"
			if Loss == "OK":
				Severity="1"
				Type="2"
				Summary="%s到%s没有丢包,状态正常" % (devicename,result['Target'])
			else:
				Severity=severity
				Type="1"
				Summary="%s到%s发生丢包,状态异常" % (devicename,result['Target'])
			strs=lc_libs.lc_gen_alert(devicename,devicename,AlertGroup,AlertKey,Severity,Type,Summary)
			db.update_eventsdb(events_table,devicename,Node,AlertGroup,AlertKey,Severity,Type,Summary)
			print strs
			saveData(devicename,result['Target'],result['Rtt'],result['Loss'])			

	except Exception:
		excinfo=traceback.format_exc()
		logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
		logfile.write(logdate+" :\n"+excinfo+" "+devicename+"\n")
		logfile.flush()
		time.sleep(1)

def saveData(devicename,Target,Rtt,Loss):
	Time=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
	expr={'Source':devicename,'Target':Target}
	datas={'Source':devicename,'Target':Target,'Rtt':Rtt,'Loss':Loss,'Time':Time}
	sortcont=[("Source",pymongo.ASCENDING),("Target",pymongo.ASCENDING)]
	opts=db.queryData(ipsla_table,expr,sortcont,0)
	res=db.genResult(opts)
	if len(res)==0:
		db.insertDatas(ipsla_table,datas)
	else:
		db.updateData(ipsla_table,expr,datas)


if __name__ == "__main__":

	lchome=lc_libs.lc_getlchome()
	scname=sys.argv[0].split('.')[0]
	logfilename=lchome+'/log/'+scname+'.log'
	confname=lchome+'/conf/'+scname+'.conf'

	today=time.strftime('%Y%m%d',time.localtime())
	os.system("mv %s %s.%s" % (logfilename,logfilename,today))

	logfile=file(logfilename,'a')
	logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
	logfile.write(logdate+" Started.\n")
	logfile.flush()

	agent_hostname=lc_libs.lc_gethostname()

	try:
		#初始化数据库

		db=lc_libs.lc_mongodb_operater('127.0.0.1',27017)

		db.connect()
		Conn=db.getConn()
		if Conn==None:
			print "Can not Connect to the MondbDB"
			exit(0)

		events_dbname='lc_events'
		events_tablename='lc_events'

		events_db=db.useDatabase(events_dbname)
		events_table=db.UseCollection(events_db,events_tablename)

		ipsla_tablename='lc_ipsla'
		ipsla_table=db.UseCollection(events_db,ipsla_tablename)

	except Exception:
		excinfo=traceback.format_exc()
		logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
		logfile.write(logdate+" 初始化数据库失败:\n"+excinfo+"\n")
		logfile.flush()
		exit(0)

	#主程序
	MonitorList = []

	for lines in open(confname):
		if lines[0] == '#' or lines.split("\t")[0] not in (agent_hostname,'default'):
			continue

		line=lines.strip('\r\n').split('\t')
		dconf={}
		dconf['agent_hostname']=line[0]
		dconf['devicename']=line[1]
		dconf['deviceip']=line[2]
		dconf['devicetype']=line[3]
		dconf['threshold']=line[4]
		dconf['interval']=line[5]
		dconf['severity']=line[6]
		dconf['schedule']=line[7]
		dconf['holiday']=line[8]

		MonitorList.append(dconf)

	serverinfo={
		'172.24.16.51':'front1',
		'172.24.16.52':'front2',
		'172.24.16.53':'front3',
		'172.24.16.54':'front4',
		'172.24.16.55':'front5',
		'172.24.20.56':'front6',
		'172.24.20.57':'front7',
		'172.24.20.58':'front8',
		'172.24.20.59':'front9',
		'172.24.20.60':'front10',
		'172.24.16.31':'mdkernel1',
		'172.24.16.32':'mdkernel2',
		'172.24.16.33':'mdkernel3',
		'172.24.16.34':'mdkernel4',
		'172.24.20.35':'mdkernel5',
		'172.24.20.36':'mdkernel6',
		'172.24.20.37':'mdkernel7',
		'172.24.20.38':'mdkernel8'
	}
	
	index={
		'1':'172.24.16.51',
		'2':'172.24.16.52',
		'3':'172.24.16.53',
		'4':'172.24.16.54',
		'5':'172.24.16.55',
		'6':'172.24.16.31',
		'7':'172.24.16.32',
		'8':'172.24.16.33',
		'9':'172.24.16.34'
	}

	usedtime=0
	
	while True:
		time.sleep(1)
		realtime=int(time.time())
		
		logdate=time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
		holiday_state = lc_libs.lc_isholiday()
		
		threads = []
		for i in MonitorList:
			if int(i['holiday']) == 1 and holiday_state == True:
				continue
				
			time_state = lc_libs.lc_schedule(i['schedule'])
			if time_state == False:
				continue
			
			flag=realtime%int(i['interval'])
			#print flag
			if flag<=usedtime:
				#print i
				t = threading.Thread(target=func,args=(i,))
				threads.append(t)
		
		for t in threads:
			t.start()
			while True:
				#print len(threading.enumerate())
				time.sleep(0.01)
				if(len(threading.enumerate()) < 100):
					break

		#排除执行程序导致的时间差
		usedtime=int(time.time())-realtime
		#print "usedtime:%s" % usedtime
